package Game;

import java.io.File;
import java.io.IOException;

import java.util.ArrayList;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.RescaleOp;

import javax.imageio.ImageIO;
import javax.swing.JPanel;

import Components.TetrisPlayground;

import smash_tris.Grid;
import smash_tris.TetrisPiece;

public class TetrisGame extends JPanel {
	Grid playfield;
	TetrisPiece piece;
	int curScore;
	Integer px = 0;
	Integer py = 2;
	private ArrayList<Image> blocks = new ArrayList<Image>();
	private Image table;
	private String DIR = "picture/playground_pics/";

	public TetrisGame(int xs, int ys) {
		playfield = new Grid(xs, ys, 0);
		clear();
		piece = new TetrisPiece();
		py = 0;
		px = 2;
		curScore = 0;

		Color color = new Color(255, 255, 255, 100);
		this.setBackground(color);

		try {
			table = ImageIO.read(new File(DIR + "table.png"));
			for (int i = 1; i < 8; i++) {
				blocks.add(ImageIO.read(new File(DIR + i + ".png")));
			}
		} catch (IOException e) {
			System.out.println("B��d z wczytaniem obrazk�w tetrisa");
			e.printStackTrace();
		}

	}

	void clear() {
		playfield.fill(0, 0, playfield.sizex(), playfield.sizey(), 0);
	}

	public Grid getPlayfield() {
		return this.playfield;
	}

	public TetrisPiece getPiece() {
		return this.piece;
	}

	public Integer getPx() {
		return px;
	}

	public Integer getPy() {
		return py;
	}

	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		Graphics2D g2 = (Graphics2D) g;

		g2.drawImage(table, 0, 0, null);


		for (int j = 0; j < playfield.sizey(); j++)
			for (int i = 0; i < playfield.sizex(); i++)
				if (playfield.getGrid()[i][j] > 0)
					g2.drawImage(blocks.get(playfield.getGrid()[i][j] - 1),
							(19 * i) + 6, (20 * j) - 3, null);

		for (int j = 0; j < piece.sizey(); j++)
			for (int i = 0; i < piece.sizex(); i++)
				if (piece.getGrid()[i][j] > 0) {
					g2.drawImage(blocks.get(piece.getGrid()[i][j] - 1),
							(19 * (i + px)) + 6, (20 * (j + py)) - 3, null);
				}

	}

	public boolean step() {
		if (playfield.compare(piece, px, py + 1)) {
			// Put down the piece
			playfield.put_on(piece, px, py);
			// Clear out full lines
			for (int j = playfield.sizey() - 1; j >= 0; j--)
				while (testFullLine(j) == true) {
					deleteLine(j);
					curScore += 10;
				}

			// Put on a new piece
			piece = new smash_tris.TetrisPiece();
			py = 0;
			px = 2;
			if (playfield.compare(piece, px, py))
				return true;
		}
		py++;
		return false;
	}

	private boolean testFullLine(int y) {
		for (int i = 0; i < playfield.sizex(); i++)
			if (playfield.grid[i][y] == 0)
				return false;
		return true;
	}

	private void deleteLine(int y) {
		for (int j = y; j > 0; j--)
			for (int i = 0; i < playfield.sizex(); i++)
				playfield.grid[i][j] = playfield.grid[i][j - 1];
		for (int i = 0; i < playfield.sizex(); i++)
			playfield.grid[i][0] = 0;
	}

	// Data-returning methods

	public int score() {
		return curScore;
	}

	// Game-play interface methods

	public void move_left(int i) {
		if (playfield.compare(piece, px - i, py))
			return; // Should we throw an exception here?
		px -= i;
	}

	public void move_left() {
		move_left(1);
	}

	public void move_right(int i) {
		if (playfield.compare(piece, px + i, py))
			return; // Should we throw an exception here?
		px += i;
	}

	public void move_right() {
		move_right(1);
	}

	public void rotate_cw() {
		TetrisPiece test = new TetrisPiece(piece);
		test.rotate_cw();
		if (!playfield.compare(test, px, py))
			piece = test;
	}

	public void rotate_ccw() {
		TetrisPiece test = new TetrisPiece(piece);
		test.rotate_ccw();
		if (!playfield.compare(test, px, py))
			piece = test;
	}

	public void drop() {
		while (!playfield.compare(piece, px, py + 1))
			py++;
	}

	public void setState(TetrisPiece eG, Grid eP, Integer pX, Integer pY) {
		// playfield = eP;
		this.px = pX;
		this.py = pY;
		piece = eG;
		this.step1();
		this.repaint();
	}

	public int getScore() {
		return this.curScore;
	}

	public void step1() {
		if (playfield.compare(piece, px, py + 1)) {
			// Put down the piece
			playfield.put_on(piece, px, py);
			// Clear out full lines
			for (int j = playfield.sizey() - 1; j >= 0; j--)
				while (testFullLine(j) == true) {
					deleteLine(j);
					// Simple scoring function
					curScore += 10;
				}

		}
	}

	public void setScore(int sc) {
		this.curScore = sc;
	}

}
